Popular Searches
Popular Course Categories
Popular Courses

Using else and finally Blocks

Using else and finally Blocks

Exception Handling and Debugging

Using else and finally Blocks in Python

Course: Python Training

Topic: Using else and finally Blocks

Course Link: Python Training Course

Demo Link: Register for a Course Demo

Academy Website: JustAcademy


1. Introduction to else and finally Blocks

Python provides try, except, else, and finally blocks to handle exceptions and control what happens when code succeeds, fails, or finishes. These blocks make programs more reliable by separating normal execution, error handling, and cleanup operations.

The else block runs when the statements inside the associated try block complete without raising an exception. The finally block runs when control leaves the associated try statement, whether an exception occurred or not, subject to exceptional termination of the Python process.

2. Learning Objectives

  • Understand the purpose of else and finally in exception handling.
  • Learn the correct syntax and execution order of exception-handling blocks.
  • Distinguish between else and finally.
  • Use these blocks for validation, file operations, database work, and resource cleanup.
  • Identify common mistakes and apply exception-handling best practices.

3. Understanding the try and except Blocks

Before using else and finally, understand the roles of try and except.

  • try: Contains code that may raise an exception.
  • except: Handles a matching exception raised inside the try block.
  • else: Runs if the try block finishes without an exception.
  • finally: Runs as control exits the exception-handling construct, commonly for cleanup.
try:
    number = int(input("Enter a number: "))
except ValueError:
    print("Please enter a valid integer.")
else:
    print("You entered:", number)
finally:
    print("Execution has reached the cleanup stage.")

In this example, a valid integer leads to the else block. If the input cannot be converted to an integer, the except block handles the ValueError. The finally block runs in either case.

4. Understanding the else Block

The else block is optional and must follow the try block and any except clauses. It is useful for placing code that should run only when the operation inside try succeeds.

Syntax

try:
    # Code that may raise an exception
    operation()
except SomeError:
    # Handle the expected exception
    handle_error()
else:
    # Runs if the try block succeeds
    process_success()

Example: Converting Input to an Integer

user_input = "125"

try:
    value = int(user_input)
except ValueError:
    print("Conversion failed.")
else:
    print("Conversion successful.")
    print("Value:", value)

Output:

Conversion successful.
Value: 125

If user_input were set to "hello", converting it to an integer would raise ValueError. The except block would run, and the else block would be skipped.

Why Use else?

  • Separates successful operations from error-handling logic.
  • Keeps the try block focused on statements that may fail.
  • Prevents unrelated statements from being accidentally covered by the same exception handler.
  • Makes code easier to read, test, and maintain.

5. Understanding the finally Block

The finally block is designed for operations that should generally be performed as execution leaves a try statement. It is commonly used to release resources, close files, disconnect from services, or restore a temporary state.

Syntax

try:
    perform_operation()
except SomeError:
    handle_error()
finally:
    cleanup_resources()

Example: Running finally After Success or Failure

try:
    print("Starting operation")
    result = 10 / 2
    print("Result:", result)
except ZeroDivisionError:
    print("Cannot divide by zero.")
finally:
    print("Operation finished.")

Output:

Starting operation
Result: 5.0
Operation finished.

If the divisor changes to zero, Python raises ZeroDivisionError. The exception handler runs, and the finally block still executes as control leaves the construct.

Common Uses of finally

  • Closing a file that was opened manually.
  • Releasing locks in threaded programs.
  • Closing database connections or cursors when appropriate.
  • Restoring temporary configuration changes.
  • Cleaning up temporary resources after a failed operation.

6. Using else and finally Together

Both blocks can appear in the same exception-handling statement. The else block handles the success path, while finally handles cleanup or other actions that should occur as control leaves the construct.

try:
    number = int("42")
except ValueError:
    print("Invalid number.")
else:
    print("Number processed successfully:", number)
finally:
    print("Processing attempt completed.")

Output:

Number processed successfully: 42
Processing attempt completed.

If conversion fails, the except block runs, the else block is skipped, and the finally block runs. If conversion succeeds, the else block runs before the finally block.

7. Execution Order of Exception-Handling Blocks

The following table summarizes the typical execution flow for a try statement containing these blocks.

Situation Execution Order Does else Run? Does finally Run?
No exception occurs in try try → else → finally Yes Yes
A matching exception is handled try → except → finally No Yes
An unhandled exception occurs try → finally → exception propagates No Yes, during normal exception unwinding
A return statement exits the try block try → finally No, if the return exits try before else Yes

Important: The table describes ordinary Python control flow. Abrupt process termination, such as a forced process kill or certain interpreter shutdown failures, can prevent cleanup code from running.

8. Example: Handling Division Safely

This example demonstrates input conversion, division, success handling, and final reporting.

def divide_numbers(first, second):
    try:
        first = float(first)
        second = float(second)
        result = first / second
    except ValueError:
        print("Both inputs must be numeric.")
    except ZeroDivisionError:
        print("The divisor cannot be zero.")
    else:
        print("Division successful.")
        print("Result:", result)
    finally:
        print("Division attempt completed.")

divide_numbers("20", "4")
divide_numbers("20", "0")
divide_numbers("twenty", "4")

Explanation:

  • The first call succeeds, so the else block prints the result.
  • The second call raises ZeroDivisionError, which is handled by its matching except block.
  • The third call raises ValueError during conversion.
  • The finally block runs for each call as control leaves the construct.

9. Example: File Handling with finally

When a file is opened manually, the finally block can ensure it is closed after reading, even if an error occurs.

file = None

try:
    file = open("sample.txt", "r", encoding="utf-8")
    content = file.read()
except FileNotFoundError:
    print("The requested file does not exist.")
except OSError as error:
    print("File operation failed:", error)
else:
    print("File content:")
    print(content)
finally:
    if file is not None:
        file.close()
        print("File closed.")

The file is closed if it was successfully opened, regardless of whether reading succeeds or fails. The else block displays the content only when the statements in try finish without an exception.

Preferred alternative: For most file operations, use a with statement. It manages the file's lifetime automatically and is usually simpler and safer.

try:
    with open("sample.txt", "r", encoding="utf-8") as file:
        content = file.read()
except FileNotFoundError:
    print("The requested file does not exist.")
except OSError as error:
    print("Could not read the file:", error)
else:
    print(content)

10. Example: Database Operation and Cleanup

Database applications may need to release cursors or connections even when a query fails. The exact cleanup strategy depends on the database driver and transaction requirements.

connection = None
cursor = None

try:
    # Replace this section with code from your database driver.
    connection = create_connection()
    cursor = connection.cursor()
    cursor.execute("SELECT name FROM students")
except DatabaseError as error:
    print("Database operation failed:", error)
else:
    rows = cursor.fetchall()
    print("Records:", rows)
finally:
    if cursor is not None:
        cursor.close()
    if connection is not None:
        connection.close()
    print("Database resources cleaned up.")

Note: create_connection() and DatabaseError are placeholders for functions and exception types supplied by the database library you use. In production code, import the correct driver, manage transactions deliberately, and ensure cleanup errors do not unintentionally hide the original failure.

11. Difference Between else and finally

Feature else Block finally Block
Primary purpose Runs success-path code. Runs cleanup or finalization code as control leaves the construct.
Execution condition Only if the try block completes without an exception. Normally runs whether an exception occurs or not.
Runs after a handled exception? No. Yes.
Runs after an unhandled exception? No. Yes, during normal exception unwinding.
Typical use Process a result after a successful operation. Close resources or restore state.
Can it be omitted? Yes. Yes.

12. Can finally Run When an Exception Is Not Handled?

Yes. If an exception is not caught by any matching except clause, Python normally executes the associated finally block before propagating the exception to the caller.

try:
    print("Before error")
    result = 10 / 0
finally:
    print("Cleanup before the error propagates")

Output before the traceback:

Before error
Cleanup before the error propagates

After the finally block runs, the ZeroDivisionError remains unhandled and propagates unless another surrounding handler catches it.

13. Important Caution: return in finally

Avoid using return inside a finally block unless overriding a pending return or exception is intentional. A return from finally can suppress an exception or replace a value returned earlier, making the program difficult to debug.

def risky_function():
    try:
        return 10
    finally:
        return 20

print(risky_function())

Output:

20

The return 20 in finally overrides the earlier return value. Similarly, an exception raised in finally can replace an exception that was already propagating. Keep finally focused on cleanup and avoid returns or unrelated control-flow changes inside it.

14. Common Mistakes to Avoid

  • Putting success logic in finally: Use else when code should run only after a successful try block.
  • Catching every exception without a reason: Prefer specific exceptions, such as ValueError or OSError, where practical.
  • Assuming finally means success: It runs after failure too; it does not indicate that the operation succeeded.
  • Using finally instead of a context manager: Prefer with for files, locks, and supported resources.
  • Returning from finally: This can override pending returns or suppress exceptions.
  • Ignoring cleanup failures: Handle cleanup errors thoughtfully when they could hide the original exception.
  • Writing too much code inside try: Keep the block limited to operations expected to raise the exceptions you intend to handle.

15. Best Practices

  • Keep the try block small and focused.
  • Use except to handle known and recoverable failures.
  • Place success-only processing inside else.
  • Use finally for essential cleanup or state restoration.
  • Use context managers, such as with open(...), whenever they provide automatic resource management.
  • Do not silently discard exceptions that the application needs to report or investigate.
  • Write tests for successful execution, expected exceptions, and cleanup behavior.
  • Remember that finally cannot guarantee cleanup if the process is forcibly terminated.

16. Practice Exercises

  1. Write a program that converts a string into an integer. Use else to display the converted value and finally to print a completion message.
  2. Create a division program that handles invalid input and division by zero.
  3. Read a text file and handle missing-file errors. Use a context manager or a finally block to ensure the file is closed.
  4. Write a function that performs a calculation and demonstrates the execution order of try, except, else, and finally.
  5. Experiment with a return statement in try and another in finally. Explain why the final return value may differ from the first.

17. Mini Project: Safe File Processing Utility

Goal: Build a utility that reads a text file, counts its lines, reports success or failure, and clearly separates successful processing from error handling.

Requirements

  • Accept a file path.
  • Use a try block to open and read the file.
  • Handle FileNotFoundError and other relevant OSError exceptions.
  • Use else to print the number of lines only when reading succeeds.
  • Use finally to print a completion message.
  • Prefer a with statement so Python closes the file automatically.

Sample Solution

def count_lines(path):
    try:
        with open(path, "r", encoding="utf-8") as file:
            lines = file.readlines()
    except FileNotFoundError:
        print("Error: file not found.")
    except OSError as error:
        print("Error reading file:", error)
    else:
        print("Total lines:", len(lines))
    finally:
        print("File processing attempt completed.")

count_lines("sample.txt")

This project reinforces how to separate normal processing, error handling, and final reporting. The with statement manages file closure, while the finally block reports that the attempt has ended.

18. Interview Questions and Answers

Q1. What is the purpose of the else block in exception handling?

The else block runs when the associated try block completes without raising an exception. It is useful for success-only operations.

Q2. Why is the finally block used?

The finally block is generally used for cleanup and finalization. It normally runs as control leaves the try statement, whether the operation succeeds or raises an exception.

Q3. Does else run if an exception occurs in try?

No. If the try block raises an exception, the else block is skipped.

Q4. Does finally run if the exception is not handled?

Normally, yes. The finally block runs during exception propagation, and then the unhandled exception continues upward.

Q5. Can try, except, else, and finally be used together?

Yes. A common arrangement is try, one or more except clauses, optional else, and optional finally, in that order.

Q6. What is the main difference between else and finally?

else runs only after the try block succeeds. finally normally runs as control leaves the construct, including when an exception occurs.

Q7. Is finally always guaranteed to execute?

No. It normally executes during ordinary control flow and exception propagation, but forced process termination or certain interpreter failures can prevent it from running.

Q8. Is finally necessary when using with?

Usually not for the resource managed by the with statement. A context manager handles its resource cleanup, so an additional finally block may be unnecessary unless other finalization is required.

19. Quick Revision

  • try contains code that may raise an exception.
  • except handles matching exceptions.
  • else runs when the try block completes without an exception.
  • finally normally runs as control leaves the exception-handling construct.
  • Use else for success-only logic and finally for cleanup.
  • Prefer context managers for resources that support them.
  • Avoid return statements inside finally because they can suppress exceptions or override return values.

20. Conclusion

The else and finally blocks help Python developers write clear and dependable exception-handling code. Use else to perform operations that depend on the success of the try block, and use finally for cleanup and finalization that should normally happen whether the operation succeeds or fails. Combined with specific exception handlers and context managers, these techniques make applications easier to maintain and troubleshoot.

To learn more about Python programming, visit the JustAcademy Python Training Course, explore the course demo registration page, or visit the JustAcademy website.

whatsapp